package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"ota-backend/config"
	"ota-backend/handlers"
	"ota-backend/storage"
	"path/filepath"
	"strings"

	"github.com/gin-contrib/cors"
	"github.com/gin-gonic/gin"
)

func main() {
	// 初始化配置
	if err := config.InitConfig(); err != nil {
		log.Fatalf("Failed to initialize config: %v", err)
	}

	// 初始化数据库
	if err := config.InitDatabase(); err != nil {
		log.Fatalf("Failed to initialize database: %v", err)
	}

	// 创建存储目录
	storagePath := config.GetStoragePath()
	if err := os.MkdirAll(storagePath, 0755); err != nil {
		log.Fatalf("Failed to create storage directory: %v", err)
	}

	// 创建数据目录
	dataPath := "data"
	if err := os.MkdirAll(dataPath, 0755); err != nil {
		log.Fatalf("Failed to create data directory: %v", err)
	}

	// 初始化存储
	localStorage := storage.NewLocalStorage(storagePath)

	// 启动防爆破保护清理例程
	bfp := handlers.NewBruteForceProtection()
	bfp.StartCleanupRoutine()

	// 设置Gin模式
	gin.SetMode(gin.ReleaseMode)

	// 创建Gin引擎
	r := gin.Default()

	// 配置Gin以处理大文件
	r.MaxMultipartMemory = 100 << 20 // 100 MB

	// 配置CORS
	corsConfig := cors.DefaultConfig()
	corsConfig.AllowAllOrigins = true
	corsConfig.AllowMethods = []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}
	corsConfig.AllowHeaders = []string{"Origin", "Content-Type", "Accept", "Authorization"}
	r.Use(cors.New(corsConfig))

	// 获取content-path配置
	contentPath := config.GetContentPath()
	log.Printf("应用程序上下文路径: %s", contentPath)

	// 设置路由 - 传入content-path
	handlers.SetupRoutes(r, localStorage, contentPath)

	// 健康检查 - 放在content-path下
	healthPath := contentPath
	if contentPath != "/" {
		healthPath = contentPath + "/health"
	} else {
		healthPath = "/health"
	}
	r.GET(healthPath, func(c *gin.Context) {
		c.JSON(200, gin.H{
			"status":  "ok",
			"message": "OTA服务运行正常",
		})
	})

	// 静态文件服务 - 提供前端文件
	webDir := "./web"
	if _, err := os.Stat(webDir); err == nil {
		log.Printf("启用前端静态文件服务: %s", webDir)

		// 提供静态文件 - 放在content-path下
		staticPath := contentPath
		if contentPath != "/" {
			staticPath = contentPath + "/static"
		} else {
			staticPath = "/static"
		}

		// 自定义静态文件处理，解决大文件传输问题
		staticHandler := func(c *gin.Context) {
			filePath := c.Param("filepath")
			if filePath != "" && filePath[0] == '/' {
				filePath = filePath[1:]
			}

			staticFile := filepath.Join(webDir, "static", filePath)

			// 检查文件是否存在
			if _, err := os.Stat(staticFile); os.IsNotExist(err) {
				c.JSON(http.StatusNotFound, gin.H{"error": "File not found: " + staticFile})
				return
			}

			// 设置适当的缓存头
			c.Header("Cache-Control", "public, max-age=31536000")

			// 直接提供文件
			c.File(staticFile)
		}

		// 同时处理GET和HEAD请求
		r.GET(staticPath+"/*filepath", staticHandler)
		r.HEAD(staticPath+"/*filepath", staticHandler)

		// favicon - 放在content-path下
		faviconPath := contentPath
		if contentPath != "/" {
			faviconPath = contentPath + "/favicon.ico"
		} else {
			faviconPath = "/favicon.ico"
		}
		r.StaticFile(faviconPath, filepath.Join(webDir, "favicon.ico"))

		// 根路径直接返回前端页面
		r.GET(contentPath, func(c *gin.Context) {
			// 如果content-path不是根路径且URL没有尾随斜杠，重定向到带斜杠的版本
			if contentPath != "/" && !strings.HasSuffix(c.Request.URL.Path, "/") {
				c.Redirect(http.StatusMovedPermanently, c.Request.URL.Path+"/")
				return
			}
			c.File(filepath.Join(webDir, "index.html"))
		})

		// 如果content-path不是根路径，添加带斜杠的路由
		if contentPath != "/" {
			contentPathWithSlash := contentPath + "/"
			r.GET(contentPathWithSlash, func(c *gin.Context) {
				c.File(filepath.Join(webDir, "index.html"))
			})
		}

		// 处理前端路由 - 对于非API和非静态文件请求，返回index.html
		r.NoRoute(func(c *gin.Context) {
			path := c.Request.URL.Path

			// 检查是否为content-path下的路径
			if contentPath != "/" {
				if !strings.HasPrefix(path, contentPath) {
					c.JSON(http.StatusNotFound, gin.H{"error": "Path not found"})
					return
				}
				// 去除content-path前缀进行判断
				path = path[len(contentPath):]
			}

			// 如果是API请求，返回404
			if len(path) >= 4 && path[:4] == "/api" {
				c.JSON(http.StatusNotFound, gin.H{"error": "API endpoint not found"})
				return
			}

			// 如果是OTA请求，返回404
			if len(path) >= 4 && path[:4] == "/ota" {
				c.JSON(http.StatusNotFound, gin.H{"error": "OTA endpoint not found"})
				return
			}

			// 静态文件请求应该已经被静态文件路由处理了，如果到了这里说明文件不存在
			if len(path) >= 7 && path[:7] == "/static" {
				c.JSON(http.StatusNotFound, gin.H{"error": "Static file not found"})
				return
			}

			// 检查是否为content-path下的前端路由
			originalPath := c.Request.URL.Path
			if contentPath != "/" && strings.HasPrefix(originalPath, contentPath+"/") {
				// 是content-path下的前端路由，返回index.html
				c.File(filepath.Join(webDir, "index.html"))
				return
			}

			// 根路径或前端路由，返回index.html
			if contentPath == "/" || path == "" || path == "/" {
				c.File(filepath.Join(webDir, "index.html"))
				return
			}

			// 其他请求返回404
			c.JSON(http.StatusNotFound, gin.H{"error": "Path not found"})
		})
	} else {
		log.Printf("前端静态文件目录不存在: %s，仅提供API服务", webDir)

		// 如果没有前端文件，根路径返回API信息
		r.GET(contentPath, func(c *gin.Context) {
			apiEndpoint := contentPath + "/api"
			otaEndpoint := contentPath + "/ota"

			// 如果contentPath是根路径，调整端点路径
			if contentPath == "/" {
				apiEndpoint = "/api"
				otaEndpoint = "/ota"
			}

			c.JSON(200, gin.H{
				"service": "OTA管理系统API",
				"version": "1.0.0",
				"endpoints": gin.H{
					"health": healthPath,
					"api":    apiEndpoint,
					"ota":    otaEndpoint,
				},
			})
		})
	}

	// 获取服务器配置
	host := config.ViperConfig.GetString("server.host")
	port := config.ViperConfig.GetInt("server.port")

	// 启动服务器
	addr := fmt.Sprintf("%s:%d", host, port)
	log.Printf("OTA服务启动在: %s", addr)
	log.Printf("存储路径: %s", storagePath)
	log.Printf("数据库类型: %s", config.ViperConfig.GetString("database.type"))

	if err := r.Run(addr); err != nil {
		log.Fatalf("Failed to start server: %v", err)
	}
}
